

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 01/18/2021 02:49:52 PM
// Design Name: 
// Module Name: selectmap_master
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module selectmap_master
  (
   //<io-ports> of <verilog-module> selectmap_master <is>
   //<interface> Bram Ctrl <is>
   input         bram_rst_a,

   input         bram_clk_a,
   input         bram_en_a,
   input [3:0]   bram_we_a, //BRAM Port A (write port) write enable signal. Active High. Byte wise signal to width of block RAM
   input [12:0]  bram_addr_a,
   input [31:0]  bram_wrdata_a,
   output [31:0] bram_rddata_a,
   //<interface> M-AXIS of CONFIG DATA FIFO <is>
   input [31:0]  M_AXIS_selectmap_config_tdata,
   input [3:0]   M_AXIS_selectmap_config_tkeep,
   input         M_AXIS_selectmap_config_tlast,
   output        M_AXIS_selectmap_config_tready,
   input         M_AXIS_selectmap_config_tvalid,
   //<interface> S-AXIS of READ BACK DATA FIFO <is>
   output [31:0] S_AXIS_selectmap_rdbk_tdata,
   output        S_AXIS_selectmap_rdbk_tlast,
   input         S_AXIS_selectmap_rdbk_tready,
   output        S_AXIS_selectmap_rdbk_tvalid,
   //<interface> SelectMap <is>
   input         i_init_b ,
   input         i_done ,
   inout [31:0]  io_data ,
   output        o_program_b ,
   output        o_rdwr_b ,
   output        o_csi_b ,
   output        o_cclk      

    );

   
//******************************************************************
//   <parameter-define-region> of <verilog-module> selectmap_master <is>
//******************************************************************

   



   
   
   
  

   //<parameter-define> of <FSM> of <module> selectmap_master <is>

`define C_FSM_BITS 9
   
   parameter C_POS_IDLE                                 = 0  ;
   parameter C_POS_WR_DEV_INIT                          = 1  ;
   parameter C_POS_WR_DEV_PRE_CHK                       = 2  ;
   parameter C_POS_WR_DEV_DATA                          = 3  ;
   parameter C_POS_WR_DEV_POST_CHK                      = 4  ;
   parameter C_POS_WR_DEV_POST_CHK_DONE                 = 5  ;   
   parameter C_POS_RD_DEV_PRE                           = 6  ;
   parameter C_POS_RD_DEV_DATA                          = 7  ;
   parameter C_POS_REQ_PROC_OK_ERR                      = 8  ;
 

   
   parameter C_ST_IDLE                   `C_FSM_BITS'b1 << C_POS_IDLE                 ;
   parameter C_ST_WR_DEV_INIT            `C_FSM_BITS'b1 << C_POS_WR_DEV_INIT          ;
   parameter C_ST_WR_DEV_PRE_CHK         `C_FSM_BITS'b1 << C_POS_WR_DEV_PRE_CHK       ;
   parameter C_ST_WR_DEV_DATA            `C_FSM_BITS'b1 << C_POS_WR_DEV_DATA          ;
   parameter C_ST_WR_DEV_POST_CHK        `C_FSM_BITS'b1 << C_POS_WR_DEV_POST_CHK      ;
   parameter C_ST_WR_DEV_POST_CHK_DONE   `C_FSM_BITS'b1 << C_POS_WR_DEV_POST_CHK_DONE ;
   parameter C_ST_RD_DEV_PRE             `C_FSM_BITS'b1 << C_POS_RD_DEV_PRE           ;
   parameter C_ST_RD_DEV_DATA            `C_FSM_BITS'b1 << C_POS_RD_DEV_DATA          ;
   parameter C_ST_REQ_PROC_OK_ERR        `C_FSM_BITS'b1 << C_POS_REQ_PROC_OK_ERR      ;






   //<parameter-define> of <register> config_readback_ctrl_r <is>
`define CONFIG_READBACK_SELECT      1
`define CONFIG_READBACK_START       0

`define CONFIG_WRITE_ACTIVE = 1'b0 ; 
`define CONFIG_READ_ACTIVE  = 1'b1 ;
   

   //<parameter-define> of <register> config_readback_status_r <is> 

`define EXCEPTION_DEVICE_PRE_CHECK_TIME_OUT          31
`define EXCEPTION_INIT_B_GET_LOW_AFTER_WRITE_DATA    30
`define EXCEPTION_DEVICE_CHECK_DONE_TIME_OUT         29
`define EVENT_DEVICE_CHECK_DONE_GOOD                 0
`define EVENT_READ_DEVICE_COMPLETE                   1
   

   

   
//******************************************************************
// <signal-define-region> of <verilog-module> selectmap_master <is>   
//******************************************************************   







   //<signal-define> <FSM> <state-variable> cs, ns <is>
   reg [`C_FSM_BITS-1:0] ns;
   reg [`C_FSM_BITS-1:0] ns;

   //<signal-define> <FSM> <one-hot> <state-variable> of <state-variable> cs <is>
   wire                  s_idle                 ;
   wire                  s_wr_dev_init          ;
   wire                  s_wr_dev_pre_chk       ;
   wire                  s_wr_dev_data          ;
   wire                  s_wr_dev_post_chk      ;
   wire                  s_wr_dev_post_chk_done ;
   wire                  s_rd_dev_pre           ;
   wire                  s_rd_dev_data          ;
   wire                  s_req_proc_ok_err      ;   


   
//control, status register for the selectmap_master
   wire [31:0] config_readback_ctrl_r;
   wire [31:0] config_readback_len_r;
   
   reg  [31:0] config_readback_status_r;
   
   
   reg                   config_start_r1;
   reg                   config_start_r2;

   wire                  config_start_pp;
   wire                  config_wr_n;
 

   //<definition> <output> <registers> of <interface> SelectMap <is>
   reg                program_b_r ;
   reg                rdwr_b_r    ;
   reg                csi_b_r     ;
   reg [31:0]         out_data_r  ;
   

   

//******************************************************************
   // 
   //******************************************************************   

   //******************************************************************
   //IO assign
   assign io_data     =  config_wr_n ? 32'hz : out_data_r;
   assign o_program_b = program_b_r;
   assign o_rdwr_b    = rdwr_b_r;
   assign o_csi_b     = csi_b_r;
   assign o_cclk      = ;
   

   //<signal-define> <output> <registers> of <interface> SelectMap <is> 
//******************************************************************
   //state assign
   assign   s_idle                  = cs[ C_POS_IDLE                ];
   assign   s_wr_dev_init           = cs[ C_POS_WR_DEV_INIT         ];
   assign   s_wr_dev_pre_chk        = cs[ C_POS_WR_DEV_PRE_CHK      ];
   assign   s_wr_dev_data           = cs[ C_POS_WR_DEV_DATA         ];
   assign   s_wr_dev_post_chk       = cs[ C_POS_WR_DEV_POST_CHK     ];
   assign   s_wr_dev_post_chk_done  = cs[ C_POS_WR_DEV_POST_CHK_DONE];
   assign   s_rd_dev_pre            = cs[ C_POS_RD_DEV_PRE          ];
   assign   s_rd_dev_data           = cs[ C_POS_RD_DEV_DATA         ];
   assign   s_req_proc_ok_err       = cs[ C_POS_REQ_PROC_OK_ERR     ];   


   


   
   
   assign config_start_pp = !config_start_r2 & config_start_r1;
   assign config_wr_n = i_config_ctrl[`CONFIG_READ_WRITE_POS];


//******************************************************************  
// Sequential Region
//******************************************************************    
   //input shift of config start pulse
   always @ ( posedge i_clk or negedge i_rst_n ) begin
      if(!i_rst_n)begin
         config_start_r1 <= 0;
         config_start_r2 <= 0;
         
      end
      else begin
         config_start_r1 <= i_config_ctrl[`CONFIG_START_POS];
         config_start_r2 <= config_start_r1;
         
      end
   end

//clk=50MHz
   
  



   

   


   
     
   



   
   ////////////////////////////////////////////////////////////////////
   //event-list
   ////////////////////////////////////////////////////////////////////
   //receiver: state:C_ST_IDLE
   //type: request
   assign write_to_slave_request  = config_start_pp & (config_wr_n == CONFIG_WRITE_ACTIVE);
   assign read_from_slave_request = config_start_pp & (config_wr_n == CONFIG_READ_ACTIVE );


   assign device_init_pulse_issued = (dev_init_cnt == 20);


   assign Evt_rd_dev_complete = (rdbk_beat_cnt == rdbk_beat_cnt_max &&
                                       rdbk_data_time_cnt < rdbk_data_time_cnt_max );


   assign Exc_wr_dev_pre_chk_time_out = (i_init_b == 1'b0 && wr_dev_pre_chk_time_cnt = wr_dev_pre_chk_time_cnt_max);
   
   assign Exc_wr_dev_chk_done_time_out = (i_done == 1'b0 &&
                                                       wr_dev_data_post_chk_done_cnt == wr_dev_data_post_chk_done_cnt_max);
   
   assign read_from_device_time_out = (rdbk_beat_cnt < rdbk_beat_cnt_max &&
                                       rdbk_data_time_cnt == rdbk_data_time_cnt_max );

   //FSM part1
   always @ ( posedge i_clk or negedge i_rst_n ) begin
      if(!i_rst_n)begin
         cs <= C_ST_IDLE;
      end
      else begin
         cs <= ns;
      end
   end
   
   
   //FSM part2
   always @ ( * ) begin
      ns = 0;
      
      case(cs)
        C_ST_IDLE:begin
           if(write_to_slave_request)
             ns[C_POS_WR_DEV_INIT] = 1;
           else if(read_from_slave_request)
             ns[C_POS_RD_DEV_PRE] = 1;
           else
             ns[C_POS_IDLE] = 1;
        end
   
       
                          
        C_ST_WR_DEV_INIT:begin
           if(device_init_pulse_issued)
             ns[C_POS_WR_DEV_PRE_CHK] = 1;
           else
             ns[C_POS_WR_DEV_INIT] = 1;
           
           
        end       
        C_ST_WR_DEV_PRE_CHK:begin
           if(i_init_b == 1'b1)
             ns[C_POS_WR_DEV_DATA] = 1;
           else if(Exc_wr_dev_pre_chk_time_out)
             ns[C_POS_REQ_PROC_OK_ERR] = 1;
           else
             ns[C_POS_WR_DEV_PRE_CHK] = 1;
           
             
        end      
        C_ST_WR_DEV_DATA:begin
           if(wr_dev_data_cnt = wr_dev_data_cnt_max)
             ns[C_POS_WR_DEV_POST_CHK] = 1;
           else
             ns[C_POS_WR_DEV_DATA] = 1;
           
        end                  
        C_ST_WR_DEV_POST_CHK:begin
           if(i_init_b == 1'b1)
             ns[C_POS_WR_DEV_POST_CHK_DONE] = 1;
           else 
             ns[C_POS_REQ_PROC_OK_ERR] = 1;
           
        end
        
        
        C_ST_WR_DEV_POST_CHK_DONE:begin
           if(i_done == 1'b1 || Exc_wr_dev_chk_done_time_out)
             ns[C_POS_REQ_PROC_OK_ERR] = 1;
           
           else
             ns[C_POS_WR_DEV_POST_CHK_DONE] = 1;
           
           
        end       
        
        C_ST_RD_DEV_PRE:begin
           ns[C_POS_RD_DEV_DATA] = 1;
           
        end                  
        C_ST_RD_DEV_DATA:begin
           if(Evt_rd_dev_complete)
             ns[C_POS_REQ_PROC_OK_ERR] = 1;
           
           else
             ns[C_POS_RD_DEV_DATA] = 1;

        end                 
        C_ST_REQ_PROC_OK_ERR:begin
           ns[C_POS_IDLE] = 1;
        end                 
        
        
        




        
        
      
   end
  

   //FSM part3
   always @ ( posedge i_clk or negedge i_rst_n ) begin
      if(!i_rst_n)begin
         program_b_r <= 1;
         rdwr_b_r    <= 1;
         csi_b_r     <= 1;


         
      end
      else begin
         if(s_idle)begin
            //<operation> <deassert> <signal> csi_b_r <is>
            csi_b_r <= 1'b1;
            
            
         end
         else if(s_wr_dev_init)begin
            //<operation> <assert> <signal> program_b, rdwr_b_r <is>
            if( dev_init_cnt == 0) begin
               program_b <= 0; 
               rdwr_b_r  <= 0;
            end
            //<operation> <deassert> <signal> program_b <is>
            else if(dev_init_cnt == 10)begin
               
               program_b <= 1;
               
            end

            //<operation> <accumulate> <counter> dev_init_cnt <is>        
            if(dev_init_cnt < 20 )
              dev_init_cnt <= dev_init_cnt + 1;
            
         end // if (s_wr_dev_init)
         else if(s_wr_dev_pre_chk)begin
            //<operation, tag = "time-out"> <accumulate> <counter>  wr_dev_pre_chk_time_cnt <is>  
            if (wr_dev_pre_chk_time_cnt < wr_dev_pre_chk_time_cnt_max)
              wr_dev_pre_chk_time_cnt <= wr_dev_pre_chk_time_cnt + 1;
            else if(wr_dev_pre_chk_time_cnt == wr_dev_pre_chk_time_cnt_max)
              Exc_wr_dev_pre_chk_time_out <= 1;

         end
         else if (s_wr_dev_data)begin
            //<operation> <control> <status> M_AXIS_selectmap_config_tready_r <is>
            if( wr_dev_data_cnt < wr_dev_data_cnt_max)
              M_AXIS_selectmap_config_tready_r <= 1;
            else if (wr_dev_data_completed )
              M_AXIS_selectmap_config_tready_r <= 0 ;
                                                                          
            //<operation> <nonblocking> <write> <data> out_data_r <is> 
            out_data_r <=  M_AXIS_selectmap_config_tdata;
            csi_b_r <=  !M_AXIS_selectmap_config_tvalid;
         end
         else if(s_wr_dev_post_chk)begin
            //<operation> <check> <signal> init_b <is>
            if(i_init_b)
              Exc_init_b_get_low_after_wr_data <= 1 ;
            
         end
         else if(s_wr_dev_post_chk_done) begin
            //<operation> <accumulate> <time-out> <counter> wr_dev_data_post_chk_done_cnt <is>
            if(wr_dev_data_post_chk_done_cnt < wr_dev_data_post_chk_done_cnt_max) begin
               wr_dev_data_post_chk_done_cnt <= wr_dev_data_post_chk_done_cnt + 1;
               
            end

            //<operation> <generate> <event> Evt_wr_dev_chk_done_good <is>
            if(i_done == 1'b1)begin
               Evt_wr_dev_chk_done_good <= 1;
            end

            //<operation> <generate> <exception> <event> Exc_wr_dev_chk_done_time_out <is>
            if(i_done == 1'b0 && wr_dev_data_post_chk_done_cnt == wr_dev_data_post_chk_done_cnt_max)
              Exc_wr_dev_chk_done_time_out <= 1;
            
         end // if (s_wr_dev_post_chk_done)
         else if(s_rd_dev_pre)begin
            //<operation> <enable> <read-mode> of <interface> SelectMap Bus <is>
            rdwr_b_r <= 1;
            
         end
         else if(s_rd_dev_data)begin //read the determined length of data from the FPGA device
            //<operation, tag = "chain_node_1"> <accumulate> <data-read> <counter> rdbk_beat_cnt <is>
            if(rdbk_beat_cnt < rdbk_beat_cnt_max)
              rdbk_beat_cnt <= rdbk_beat_cnt_max + 1;

            //<operation, tag = "chain_node_2"> <nonblocking> <control> <chip-select> <signal> csi_b_r <is>
            if(rdbk_beat_cnt < rdbk_beat_cnt_max)begin
               if(S_AXIS_selectmap_rdbk_tready == 1'b1)
                 csi_b_r <= 0;
               else
                 csi_b_r <= 1;
                 
            end
            else
              csi_b_r <= 1;

            //<operation, tag = "chain_node_3"> <nonblocking> <control> <data-valid> S_AXIS_selectmap_rdbk_tvalid_r <is>
            S_AXIS_selectmap_rdbk_tvalid_r <= !csi_b_r;

            //<operation> <nonblocking> <control> <data> S_AXIS_selectmap_rdbk_tdata_r
            S_AXIS_selectmap_rdbk_tdata_r <= io_data;
            
         end // if (s_rd_dev_data)
         else if(s_req_proc_ok_err)begin //update status register
            //<operation> <copy> <response> <status> of <request>  write_to_slave_request <is>
            config_readback_status_r[`EXCEPTION_DEVICE_PRE_CHECK_TIME_OUT      ] <= Exc_wr_dev_pre_chk_time_out     ;
            config_readback_status_r[`EXCEPTION_INIT_B_GET_LOW_AFTER_WRITE_DATA] <= Exc_init_b_get_low_after_wr_data;
            config_readback_status_r[`EXCEPTION_DEVICE_CHECK_DONE_TIME_OUT     ] <= Evt_wr_dev_chk_done_good       ;
            config_readback_status_r[`EVENT_DEVICE_CHECK_DONE_GOOD             ] <= Exc_wr_dev_chk_done_time_out    ;
            
            //<operation> <copy> <response> <status> of <request>  read_from_slave_request <is>
            config_readback_status_r[`EVENT_READ_DEVICE_COMPLETE               ] <= Evt_rd_dev_complete;





            
            
         end
         
      end
   end

   
/* -----\/----- EXCLUDED -----\/-----

//template
   always @ ( posedge i_clk or negedge i_rst_n ) begin
      if(!i_rst_n)begin
         
      end
      else begin

      end
   end
 -----/\----- EXCLUDED -----/\----- */
//******************************************************************
   //Instance Region
   //******************************************************************
   
   reg_file_sm reg_file_sm_i
     (
      // Outputs
      .bram_rddata_a                    (bram_rddata_a[31:0]),
      .config_readback_ctrl_r           (config_readback_ctrl_r[31:0]),
      .config_readback_len_r            (config_readback_len_r[31:0]),
      // Inputs
      .bram_rst_a                       (bram_rst_a),
      .bram_clk_a                       (bram_clk_a),
      .bram_en_a                        (bram_en_a),
      .bram_we_a                        (bram_we_a[3:0]),
      .bram_addr_a                      (bram_addr_a[12:0]),
      .bram_wrdata_a                    (bram_wrdata_a[31:0]),
      .config_readback_status           (config_readback_status_r[31:0]));



 //******************************************************************
   //Debug Region
   //****************************************************************   

`define C_DBG_SLM
   
`ifdef C_DBG_SLM




`endif   

   







   
endmodule
